package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.user.IUserClient;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentRepay;
import com.heima.comment.pojos.ApCommentRepayLike;
import com.heima.comment.pojos.CommentRepayVo;
import com.heima.comment.service.CommentRepayService;
import com.heima.model.comment.dtos.CommentRepayDto;
import com.heima.model.comment.dtos.CommentRepayLikeDto;
import com.heima.model.comment.dtos.CommentRepaySaveDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentRepayServiceImpl implements CommentRepayService {

    @Autowired
    private IUserClient userClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 加载评论回复列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadCommentRepay(CommentRepayDto dto) {
        log.info("加载评论回复列表");
        //1.检查参数
        if(dto == null || dto.getCommentId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //要加载的最大回复评论数量
        int size = 20;

        //2.加载数据(以评论ID为条件查询：这是哪条评论下的回复评论)
        //创建一个Query对象来查询commentId与dto中commentId匹配
        // 且createdTime早于dto中的minDate的评论。
        Query query = Query.query(Criteria.where("commentId")
                .is(dto.getCommentId()).and("createdTime").lt(dto.getMinDate()));
        //对查询结果按createdTime字段进行降序排序   //设置查询结果的限制为先加载最多20条记录
        query.with(Sort.by(Sort.Direction.DESC,"createdTime")).limit(size);
        List<ApCommentRepay> list = mongoTemplate.find(query, ApCommentRepay.class);

        //3.数据封装返回
        //3.1 用户未登录
        //获取当前用户的登录信息
        ApUser user = AppThreadLocalUtil.getUser();
        if(user == null){
            log.info("用户未登录，返回的结果是：{}",list);
            return ResponseResult.okResult(list);
        }

        //3.2 用户已登录
        log.info("用户已登录，返回的结果是：{}",list);
        //需要查询当前评论中哪些数据被点赞了
        List<String> idList = list.stream().map(x -> x.getId()).collect(Collectors.toList());
        //TODO 创建第二个Query以查找哪些评论回复被当前登录用户（由authorId匹配）点赞了
        //如果当天登录人点赞了某条评论，需要高亮展示“点赞按钮”
        Query query1 = Query.query(Criteria.where("commentRepayId")
                .in(idList).and("authorId").is(user.getId()));
        //APP评论回复信息的点赞信息
        List<ApCommentRepayLike> apCommentRepayLikes = mongoTemplate.find(query1, ApCommentRepayLike.class);
        //获取apCommentRepayLikes列表，
        if(apCommentRepayLikes == null || apCommentRepayLikes.size() == 0 ){
            // 如果没有找到点赞记录，则返回原始的评论回复列表。
            return ResponseResult.okResult(list);
        }
        //创建一个空的resultList列表来存储最终要返回给用户的回复评论视图对象。
        List<CommentRepayVo> resultList = new ArrayList<>();
        //遍历每个ApCommentRepay对象（x），
        // 创建一个新的CommentRepayVo对象（视图对象）。
        list.forEach(x->{
            CommentRepayVo vo = new CommentRepayVo();
            //复制属性从x到vo。
            BeanUtils.copyProperties(x,vo);
            for (ApCommentRepayLike apCommentRepayLike : apCommentRepayLikes) {
                //检查当前回复是否在点赞列表中。
                // 若是，则设置vo的操作状态为0（表示用户已点赞）
                if(x.getId().equals(apCommentRepayLike.getCommentRepayId())){
                    vo.setOperation((short)0);
                    break;
                }
            }
            //将处理后的vo添加到结果列表中。
            resultList.add(vo);
        });
        //返回包含已处理的评论回复视图对象列表的成功响应。
        return ResponseResult.okResult(resultList);
    }

    /**
     * 发布(保存)评论回复
     * @param dto (评论id + 回复内容)
     * @return
     */
    @Override
    public ResponseResult saveCommentRepay(CommentRepaySaveDto dto) {
        //1.检查参数
        if(dto == null || StringUtils.isBlank(dto.getContent()) || dto.getCommentId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getContent().length() > 150){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,
                    "评论内容不能超过150字");
        }

        //2.判断是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if(user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.安全检查 TODO 做文本垃圾检测

        //4.保存评论
        //ApUser dbUser = userClient.findUserById(user.getId());
        ResponseResult responseResult = userClient.findUserById(user.getId());
        log.info("远程接口查询到的app端用户信息返回结果：{}",responseResult.getData());
        ApUser dbUser = null;
        log.info("responseResult.getCode()是：{}",responseResult.getCode());
        if(responseResult.getCode().equals(200)){
            log.info("远程接口调用成功");
            //获得app端用户信息(json数据)
            String apUserJson = JSON.toJSONString(responseResult.getData());
            //转换成对象
            dbUser = JSON.parseObject(apUserJson, ApUser.class);
            //通过用户ID查找当前登录用户的信息。如果用户不存在，则返回错误信息。
            if (dbUser == null) {
                log.info("当前登录信息有误");
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,
                        "当前登录信息有误");
            }
            //ApUser dbUser = userClient.findUserById(user.getId());
        }

        ApCommentRepay apCommentRepay = new ApCommentRepay();
        apCommentRepay.setAuthorId(user.getId());
        apCommentRepay.setContent(dto.getContent());
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setCommentId(dto.getCommentId());
        apCommentRepay.setAuthorName(dbUser.getName());
        apCommentRepay.setUpdatedTime(new Date());
        //初始化点赞数量
        apCommentRepay.setLikes(0);

        mongoTemplate.save(apCommentRepay);

        //5更新回复数量
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        apComment.setReply(apComment.getReply()+1);
        mongoTemplate.save(apComment);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 对评论回复的点赞(点赞数 + 1 |记录是谁点的赞)
     * @param dto (评论id + 0.点赞1：取消点赞)
     * @return
     */
    @Override
    public ResponseResult saveCommentRepayLike(CommentRepayLikeDto dto) {
        //1.检查参数
        if(dto == null || dto.getCommentRepayId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断是否登录
        ApUser user = AppThreadLocalUtil.getUser();
        if(user == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //查找指定commentRepayId的评论回复对象apCommentRepay。
        ApCommentRepay apCommentRepay = mongoTemplate.findById(dto.getCommentRepayId(), ApCommentRepay.class);

        //3.点赞  0：点赞  1：取消点赞
        //检查apCommentRepay是否存在且操作类型是否为点赞（dto.getOperation() == 0）
        if(apCommentRepay != null && dto.getOperation() == 0){
            //是点赞，将评论回复的likes数量加1
            apCommentRepay.setLikes(apCommentRepay.getLikes()+1);
            mongoTemplate.save(apCommentRepay);

            //不仅仅要增加点赞数，还需要记录当前用户对于当前评论的点赞数据记录
            //保存评论点赞数据(记录是谁点的赞)
            ApCommentRepayLike apCommentRepayLike = new ApCommentRepayLike();
            apCommentRepayLike.setCommentRepayId(apCommentRepay.getId());
            apCommentRepayLike.setAuthorId(user.getId());
            mongoTemplate.save(apCommentRepayLike);
        }else {
            //是取消点赞，更新评论点赞数量
            int tmp = apCommentRepay.getLikes()-1;
            //确保点赞数量不小于0。
            tmp = tmp < 1 ? 0 : tmp;
            apCommentRepay.setLikes(tmp);
            mongoTemplate.save(apCommentRepay);

            //删除该用户的回复评论的点赞记录
            //构建一个查询来查找数据库中与当前评论回复ID和用户ID匹配的点赞记录
            Query query = Query.query(Criteria.where("commentRepayId")
                    .is(apCommentRepay.getId())
                    .and("authorId").is(user.getId()));
            mongoTemplate.remove(query,ApCommentRepayLike.class);
        }

        //4.取消点赞
        Map<String,Object> result = new HashMap<>();
        log.info("更新后的点赞数量：{}",apCommentRepay.getLikes());
        result.put("likes",apCommentRepay.getLikes());
        return ResponseResult.okResult(result);
    }
}
